package com.castle.fortress.admin.flowable.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.castle.fortress.admin.core.constants.GlobalConstants;
import com.castle.fortress.admin.flowable.dto.AppAnalyzeDto;
import com.castle.fortress.admin.flowable.dto.FlowableAppDto;
import com.castle.fortress.admin.flowable.entity.FlowableAppEntity;
import com.castle.fortress.admin.flowable.entity.FlowableTemplateEntity;
import com.castle.fortress.admin.flowable.enums.ApproveStatusEnum;
import com.castle.fortress.admin.flowable.form.entity.FlowableFormConfigEntity;
import com.castle.fortress.admin.flowable.form.service.FlowableFormAnalyzeDataService;
import com.castle.fortress.admin.flowable.form.service.FlowableFormConfigService;
import com.castle.fortress.admin.flowable.mapper.FlowableAppMapper;
import com.castle.fortress.admin.flowable.service.FlowableAppService;
import com.castle.fortress.admin.flowable.service.FlowableTemplateService;
import com.castle.fortress.admin.system.dto.SysDeptDto;
import com.castle.fortress.admin.system.entity.SysUser;
import com.castle.fortress.admin.system.service.SysDeptService;
import com.castle.fortress.admin.utils.BizCommonUtil;
import com.castle.fortress.common.enums.DataPermissionPostEnum;
import com.castle.fortress.common.enums.LeaveTypeEnum;
import com.castle.fortress.common.utils.CommonUtil;
import com.castle.fortress.common.utils.ConvertUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.sql.Timestamp;
import java.util.*;

/**
 * 流程应用管理表 服务实现类
 *
 * @author castle
 * @since 2022-09-26
 */
@Service
public class FlowableAppServiceImpl extends ServiceImpl<FlowableAppMapper, FlowableAppEntity> implements FlowableAppService {
    @Autowired
    private SysDeptService sysDeptService;
    @Autowired
    private FlowableTemplateService flowableTemplateService;
    @Autowired
    private FlowableFormAnalyzeDataService flowableFormAnalyzeDataService;
    @Autowired
    private FlowableFormConfigService flowableFormConfigService;
    /**
    * 获取查询条件
    * @param flowableAppDto
    * @return
    */
    public QueryWrapper<FlowableAppEntity> getWrapper(FlowableAppDto flowableAppDto){
        QueryWrapper<FlowableAppEntity> wrapper= new QueryWrapper();
        if(flowableAppDto != null){
            FlowableAppEntity flowableAppEntity = ConvertUtil.transformObj(flowableAppDto,FlowableAppEntity.class);
            wrapper.like(StrUtil.isNotEmpty(flowableAppEntity.getTitle()),"title",flowableAppEntity.getTitle());
            wrapper.eq(flowableAppEntity.getFlowId() != null,"flow_id",flowableAppEntity.getFlowId());
            wrapper.eq(flowableAppEntity.getStatus() != null,"status",flowableAppEntity.getStatus());
        }
        return wrapper;
    }


    @Override
    public IPage<FlowableAppDto> pageFlowableApp(Page<FlowableAppDto> page, FlowableAppDto flowableAppDto) {
        QueryWrapper<FlowableAppEntity> wrapper = getWrapper(flowableAppDto);
        Page<FlowableAppEntity> pageEntity = new Page(page.getCurrent(), page.getSize());
        Page<FlowableAppEntity> flowableAppPage=baseMapper.selectPage(pageEntity,wrapper);
        Page<FlowableAppDto> pageDto = new Page(flowableAppPage.getCurrent(), flowableAppPage.getSize(),flowableAppPage.getTotal());
        pageDto.setRecords(ConvertUtil.transformObjList(flowableAppPage.getRecords(),FlowableAppDto.class));
        return pageDto;
    }


    @Override
    public List<FlowableAppDto> listFlowableApp(FlowableAppDto flowableAppDto){
        QueryWrapper<FlowableAppEntity> wrapper = getWrapper(flowableAppDto);
        List<FlowableAppEntity> list = baseMapper.selectList(wrapper);
        return ConvertUtil.transformObjList(list,FlowableAppDto.class);
    }

    @Override
    public IPage<FlowableAppDto> pageWithAuth(Page<FlowableAppDto> page, FlowableAppDto flowableAppDto, SysUser user) {
        Map<String,Long> pageMap = BizCommonUtil.getPageParam(page);
        FlowableAppEntity entity = ConvertUtil.transformObj(flowableAppDto,FlowableAppEntity.class);
        List<Long> authIds = new ArrayList<>();
        //非超管
        if(!user.getIsSuperAdmin()&&!user.getIsAdmin()){
            //用户
            authIds.add(user.getId());
            //部门
            authIds.add(user.getDeptId());
            //所属部门的所有父级
            if(StrUtil.isNotEmpty(user.getDeptParents())){
                String[] parents = user.getDeptParents().split(",");
                for(int i=0;i<parents.length;i++){
                    authIds.add(Long.parseLong(parents[i]));
                }
            }
//            //所属部门的所有子集
//            List<SysDeptDto> deptDtos = sysDeptService.allChildren(user.getDeptId());
//            deptDtos.forEach(item->{
//                authIds.add(item.getId());
//            });
            authIds.add(-1L);//所有人可见
        }
        List<FlowableAppEntity> list = baseMapper.ListWithAuth(pageMap,entity,authIds);
        Long total = baseMapper.countWithAuth(entity,authIds);
        Page<FlowableAppDto> pageDto = new Page(page.getCurrent(), page.getSize(),total);
        pageDto.setRecords(ConvertUtil.transformObjList(list,FlowableAppDto.class));
        return pageDto;
    }

    @Override
    public IPage<AppAnalyzeDto> pageAnalyzeFlowableApp(SysUser user, FlowableAppDto flowableAppDto) {
        if(CommonUtil.verifyParamEmpty(user,flowableAppDto,flowableAppDto.getFlowId())){
            return null;
        }
        if(flowableAppDto.getCurrent()==null){
            flowableAppDto.setCurrent(GlobalConstants.DEFAULT_PAGE_INDEX);
        }
        if(flowableAppDto.getSize()==null){
            flowableAppDto.setSize(GlobalConstants.DEFAULT_PAGE_SIZE);
        }
        Page<AppAnalyzeDto> pageDto = new Page(flowableAppDto.getCurrent(),flowableAppDto.getSize());
        pageDto.setRecords(listAnalyzeFlowableApp(user,flowableAppDto));
        pageDto.setTotal(countAnalyzeFlowableApp(user,flowableAppDto));
        return pageDto;
    }

    @Override
    public List<AppAnalyzeDto> listAnalyzeFlowableApp(SysUser user, FlowableAppDto flowableAppDto) {
        List<AppAnalyzeDto> result = new ArrayList<>();
        //未登陆用户不可使用该接口
        if(CommonUtil.verifyParamEmpty(user,flowableAppDto,flowableAppDto.getFlowId())){
            return result;
        }
        FlowableTemplateEntity templateEntity =flowableTemplateService.getById(flowableAppDto.getFlowId());
        String formKey = templateEntity.getFormKey()+"";
        //查询条件
        Map<String,Object> queryMap = new HashMap<>();
        //非用户管理员限制数据权限
        if(user!=null && !user.getIsSuperAdmin() && !user.getIsAdmin()){
            //不限
            queryMap.put("_dataAuth_flag","01");
            //查询当前用户的部门权限
            List<Long> deptIdList = user.getAuthDept();
            //剔除当前用户所在的部门ID
            if(!DataPermissionPostEnum.NO_LIMIT.getCode().equals(user.getPostDataAuth())){
                //本人
                queryMap.put("_dataAuth_flag","03");
                deptIdList.remove(user.getDeptId());
                queryMap.put("_dataAuth_userId",user.getId());
            }
            //本人及下级岗位
            if(DataPermissionPostEnum.SELF_SUB.getCode().equals(user.getPostDataAuth())){
                //本人及以下
                queryMap.put("_dataAuth_flag","02");
                List<Long> subPostList = user.getSubPost();
                queryMap.put("_dataAuth_subPostList",subPostList);
            }
            queryMap.put("_dataAuth_deptIdList",deptIdList);
        }
        if(flowableAppDto.getSize()!=null&&flowableAppDto.getCurrent()!=null){
            Integer start = (flowableAppDto.getCurrent()-1)*flowableAppDto.getSize();
            queryMap.put("_page_start",start);
            queryMap.put("_page_rows",flowableAppDto.getSize());
        }
        if(flowableAppDto.getApproveStatus()!=null){
            queryMap.put("_castle_approve_status",flowableAppDto.getApproveStatus());
        }
        List<Map<String, Object>> list = flowableFormAnalyzeDataService.queryAnalyzeListData(formKey,queryMap);
        Map<String, Map<String, String>> tbContentMap = new HashMap<>();
        if(list!=null&&list.size()>0){
            FlowableFormConfigEntity configEntity = flowableFormConfigService.getById(templateEntity.getFormKey());
            tbContentMap = flowableFormConfigService.parseTbContentData(configEntity.getTbContent());
        }
        for(Map<String, Object> map:list){
            result.add(convertToDto(map,tbContentMap));
        }
        return result;
    }

    @Override
    public Long countAnalyzeFlowableApp(SysUser user, FlowableAppDto flowableAppDto) {
        Long result= 0L;
        //未登陆用户不可使用该接口
        if(CommonUtil.verifyParamEmpty(user,flowableAppDto,flowableAppDto.getFlowId())){
            return result;
        }
        FlowableTemplateEntity templateEntity =flowableTemplateService.getById(flowableAppDto.getFlowId());
        String formKey = templateEntity.getFormKey()+"";
        //查询条件
        Map<String,Object> queryMap = new HashMap<>();
        //非用户管理员限制数据权限
        if(user!=null && !user.getIsSuperAdmin() && !user.getIsAdmin()){
            //不限
            queryMap.put("_dataAuth_flag","01");
            //查询当前用户的部门权限
            List<Long> deptIdList = user.getAuthDept();
            //查询当前用户的职位权限
            if(user.getPostId()!=null){
                //剔除当前用户所在的部门ID
                if(!DataPermissionPostEnum.NO_LIMIT.getCode().equals(user.getPostDataAuth())){
                    //本人
                    queryMap.put("_dataAuth_flag","03");
                    deptIdList.remove(user.getDeptId());
                    queryMap.put("_dataAuth_userId",user.getId());
                }
                //本人及下级岗位
                if(DataPermissionPostEnum.SELF_SUB.getCode().equals(user.getPostDataAuth())){
                    //本人及以下
                    queryMap.put("_dataAuth_flag","02");
                    List<Long> subPostList = user.getSubPost();
                    queryMap.put("_dataAuth_subPostList",subPostList);
                }
            }
            queryMap.put("_dataAuth_deptIdList",deptIdList);
        }
        if(flowableAppDto.getSize()!=null&&flowableAppDto.getCurrent()!=null){
            Integer start = (flowableAppDto.getCurrent()-1)*flowableAppDto.getSize();
            queryMap.put("_page_start",start);
            queryMap.put("_page_rows",flowableAppDto.getSize());
        }
        if(flowableAppDto.getApproveStatus()!=null){
            queryMap.put("_castle_approve_status",flowableAppDto.getApproveStatus());
        }
        return flowableFormAnalyzeDataService.queryAnalyzeCount(formKey,queryMap);
    }

    @Override
    public AppAnalyzeDto infoAnalyzeFlowableApp(FlowableAppDto flowableAppDto) {
        AppAnalyzeDto dto = null;
        //未登陆用户不可使用该接口
        if(CommonUtil.verifyParamEmpty(flowableAppDto,flowableAppDto.getFlowId(),flowableAppDto.getId())){
            return dto;
        }
        FlowableTemplateEntity templateEntity =flowableTemplateService.getById(flowableAppDto.getFlowId());
        String formKey = templateEntity.getFormKey()+"";
        Map<String, Object> m=flowableFormAnalyzeDataService.queryAnalyzeInfoData(formKey,flowableAppDto.getId()+"");
        Map<String, Map<String, String>> tbContentMap = new HashMap<>();
        if(m!=null&&!m.isEmpty()){
            FlowableFormConfigEntity configEntity = flowableFormConfigService.getById(templateEntity.getFormKey());
            tbContentMap= flowableFormConfigService.parseTbContentData(configEntity.getTbContent());
            dto = convertToDto(m,tbContentMap);
        }
        return dto;
    }

    private AppAnalyzeDto convertToDto(Map<String, Object> map,Map<String, Map<String, String>> tbContentMap){
        AppAnalyzeDto dto = new AppAnalyzeDto();
        List<Map<String,Object>> bizDatas=new ArrayList<>();
        BeanUtil.fillBeanWithMap(map,dto,true);
        //时间格式转换
        if(dto.get_castle_apply_date()!=null){
            dto.set_castle_apply_date(new Date(dto.get_castle_apply_date().getTime()));
        }
        if(dto.get_castle_approve_date()!=null){
            dto.set_castle_approve_date(new Date(dto.get_castle_approve_date().getTime()));
        }
        //转换审批状态
        if(StrUtil.isNotEmpty(dto.get_castle_approve_status())){
            dto.set_castle_approve_status(ApproveStatusEnum.getNameByCode(Integer.parseInt(dto.get_castle_approve_status())));
        }
        //业务数据处理
        for(String key:map.keySet()){
            if(key.indexOf("_castle_")!=0 && !key.equals("id")){
                Map<String,Object> v = new HashMap<>();
                v.put("colId",key);
                v.put("colName",key);
                v.put("colValue",map.get(key));
                Map<String, String> colMap = tbContentMap.get(key);
                if(colMap!=null && !colMap.isEmpty()){
                    v.put("colName",colMap.get("colName"));
                    //时间类型特殊处理下
                    if("datetime".equals(colMap.get("colType"))){
                        if(map.get(key) instanceof Timestamp){
                            v.put("colValue",new Date(((Timestamp)map.get(key)).getTime()));
                        }
                        v.put("colValue",DateUtil.format((Date)v.get("colValue"),DatePattern.NORM_DATETIME_FORMATTER));
                    }
                }
                if ("fortress_holiday".equals(key)){
                    JSONObject value =  new JSONObject(map.get(key));
                    //{"type":"1588093998299570177","startTime":"2022-11-10","endTime":"2022-11-10","startType":"am","endType":"am","leaveDuration":0.5}
                    dto.set_castle_leave_type(value.get("type").toString());
                    dto.set_castle_start_time(value.get("startTime").toString() +" "+ LeaveTypeEnum.getNameByCode(value.get("startType").toString()));
                    dto.set_castle_end_time(value.get("endTime").toString() +" "+ LeaveTypeEnum.getNameByCode(value.get("endType").toString()));
                    dto.set_castle_leave_duration(value.get("leaveDuration").toString());
                }
                bizDatas.add(v);
            }
        }
        dto.setBizDatas(bizDatas);
        return dto;
    }

}

